#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>


#define OCCUPY  1
#define EMPTY	0

typedef struct HASHITEM HashItem;
typedef struct HASHTABLE HashTable;
typedef HashItem ElementType;
struct HASHITEM{
	long key;
	int recordTime;
};

struct HASHTABLE{
	ElementType *elm;
	int *info;
	int tableSize;
	int prime;
};

int NextPrime(int a);
HashTable * InitHashTable(int tableSize);
void InsertHashTable(HashTable *,long);
int FindPos(HashTable*,long);
int HashValue(HashTable *,long);
int Mod(int,int);
void PrtHashTable(HashTable *);
void DestroyHashTable(HashTable *);


int main(){
	int N;
	scanf("%d",&N);
	HashTable *h=InitHashTable(N*2);
	long n1,n2;
	int p1,p2;
	for(int i=0;i<N;i++){
		scanf("%ld %ld",&n1,&n2);
		p1=FindPos(h,n1);
		if( -1 == p1 ){	//	can't find n1 in hash table
			InsertHashTable(h,n1);
		}else{
			h->elm[p1].recordTime++;
		}
		p2=FindPos(h,n2);
		if( -1 == p2 ){
			InsertHashTable(h,n2);
		}else{
			h->elm[p2].recordTime++;
		}
	}
	//printf("TableSize:%d\n",h->tableSize);
	//PrtHashTable(h);
	int resultIndex=0;
	int sameRecord=0;
	for(int i=0;i<h->tableSize;i++){
		if( h->info[i] == OCCUPY ){
			resultIndex=i;
			break;
		}
	}
	for(int i=resultIndex+1;i<h->tableSize;i++){
		if( h->info[i] == OCCUPY ){
			if( h->elm[i].recordTime > h->elm[resultIndex].recordTime ){
				resultIndex=i;
				sameRecord=0;
			}else if( h->elm[i].recordTime == h->elm[resultIndex].recordTime ){
				if( h->elm[i].key < h->elm[resultIndex].key ){
					resultIndex=i;
				}
				sameRecord++;
			}else{}
		}
	}
	if( sameRecord )
		printf("%ld %d %d",h->elm[resultIndex].key,h->elm[resultIndex].recordTime,sameRecord+1);
	else
		printf("%ld %d",h->elm[resultIndex].key,h->elm[resultIndex].recordTime);
	DestroyHashTable(h);
	return 0;
}
int NextPrime(int a){
	while( 1 ){
		int i=2;
		for( i=2; i*i <= a;i++){
			if( 0 == a%i ){
				break;
			}
		}
		if( i*i > a )
			return a;
		a++;
	}
}
int Mod(int num,int base){
	while( num>=base){
		num-=base;
	}
	while( num<0 ){
		num+=base;
	}
	return num%base;
}
HashTable * InitHashTable(int size){
	HashTable *h=malloc(sizeof(HashTable));
	h->tableSize=2*size;
	h->prime=NextPrime(h->tableSize);
	h->elm=malloc(sizeof(ElementType)*h->tableSize);
	h->info=malloc(sizeof(int)*h->tableSize);
	memset(h->info,EMPTY,sizeof(int)*h->tableSize);
	return h;
}
void InsertHashTable(HashTable *h,long key){
	int currentPos=HashValue(h,key);
	int newPos=currentPos=Mod(currentPos,h->tableSize);
	int countNum=0;
	int m;
	while( h->info[newPos]!=EMPTY ){
		countNum++;
		m=countNum%2;
		if(m){
			newPos=Mod(currentPos+(countNum+1)*(countNum+1)/4,h->tableSize);
		}else{
			newPos=Mod(currentPos-countNum*countNum/4,h->tableSize);
		}
	}
	h->info[newPos]=OCCUPY;
	h->elm[newPos]=(ElementType){.key=key,.recordTime=1};
	//h->elm[hv].key=key;
	//h->elm[hv].recordTime=1;
	return;
}
int FindPos(HashTable *h,long key){
	int currentPos=HashValue(h,key);
	int newPos=currentPos=Mod(currentPos,h->tableSize);
	int countNum=0;
	int m;
	while( h->info[newPos]==OCCUPY && h->elm[newPos].key!=key ){
		countNum++;
		m=countNum%2;
		if( m ){
			newPos=Mod(currentPos+(countNum+1)*(countNum+1)/4,h->tableSize);
		}else{
			newPos=Mod(currentPos-(countNum)*(countNum)/4,h->tableSize);
		}
	}
	if( h->info[newPos] == EMPTY )
		return -1;
	else
		return newPos;
}
int HashValue(HashTable *h,long key){
	return key%(h->prime);
}
void PrtHashTable(HashTable *h){
	for(int i=0;i<h->tableSize;i++){
		if( h->info[i] == EMPTY )
			printf("E ");
		else
			printf("%ld:%d ",h->elm[i].key,h->elm[i].recordTime);
	}
}
void DestroyHashTable(HashTable *h){
	free(h->elm);
	free(h->info);
	free(h);
	return;
}
